package com.guochuang.yunwang.promanager.controller;


import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.guochuang.yunwang.promanager.annotation.CancelLoginIntercept;
import com.guochuang.yunwang.promanager.config.OssConfig;
import com.guochuang.yunwang.promanager.domain.User;
import com.guochuang.yunwang.promanager.domain.vo.UserAvatorVO;
import com.guochuang.yunwang.promanager.domain.vo.UserRoleVO;
import com.guochuang.yunwang.promanager.domain.vo.UserSearchVO;
import com.guochuang.yunwang.promanager.domain.vo.UserVO;
import com.guochuang.yunwang.promanager.exception.ParamException;
import com.guochuang.yunwang.promanager.service.ProjectService;
import com.guochuang.yunwang.promanager.service.UserService;
import com.guochuang.yunwang.promanager.utils.*;
import com.guochuang.yunwang.promanager.utils.OssUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Api(tags = "用户接口模块")
@RestController
@Slf4j
public class UserController {

    @Autowired
    private SimpleDateFormat simpleDateFormat;

    @Autowired
    private UserService userService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private OssConfig ossConfig;


    @GetMapping(value = "/get/all/roles/{uid}")
    @ApiOperation(value = "根据用户查询所有角色和已选角色")
    public ResultEntity getAllRoles(@PathVariable Integer uid) {
        log.info(String.format("用户id为%d，执行getAllRoles方法。。。", uid));
        if (uid == null) {
            log.error("执行getAllRoles方法时uid为空！");
            throw new ParamException(ProjectConstant.PARAM_ERROR_MESSAGE);
        }

        UserRoleVO rec = projectService.getRolesList(uid);

        return ResultEntity.successWithData(rec);
    }

    @PutMapping(value = "/update/user/roles/{uid}")
    @ApiOperation(value = "修改用户角色")
    public ResultEntity updateRoleToUser(@PathVariable Integer uid, @RequestBody List<Integer> rolse) {

        Integer nums = userService.updateUserRoles(uid, rolse);

        if (nums > 0) {
            return ResultEntity.successWithoutData();
        } else {
            return ResultEntity.failed(ProjectConstant.USER_CHANGE_FAILED);
        }
    }


    // 注意get请求不能使用RequestBody注解
    @PostMapping(value = "/get/user/infos/by/params")
    @ApiOperation("根据多条件查询用户信息")
    @RequiresPermissions(value = {"user:find"})
    public ResultEntity searchUserByParams(@RequestBody UserSearchVO uservo) {

        PageInfo pageinfo = userService.findUserByParmas(uservo);

        Map<String, Object> rec = new HashMap<>();

        rec.put("total", pageinfo.getTotal());

        rec.put("data", pageinfo.getList());

        return ResultEntity.successWithData(rec);
    }

    @PutMapping(value = "/update/user/by/uid")
    @ApiOperation("根据用户id修改用户信息")
    @RequiresPermissions(value = {"user:update"})
    public ResultEntity updateUserByUid(@RequestBody User user) {
        String timestr = simpleDateFormat.format(System.currentTimeMillis());

        user.setGmtModified(timestr);
        // 给密码加密
        user.setPassword(ProjectUtils.md5(user.getPassword()));

        Integer nums = userService.updateUser(user);

        if (nums > 0) {
            return ResultEntity.successWithoutData();
        } else {
            return ResultEntity.failed(ProjectConstant.USER_CHANGE_FAILED);
        }
    }


    @PostMapping(value = "/add/new/user")
    @ApiOperation("添加新用户")
    @RequiresPermissions(value = {"user:add"})
    public ResultEntity addNewUser(@RequestBody User user) {

        String timestr = simpleDateFormat.format(System.currentTimeMillis());

        user.setIsDeleted(0);

        user.setGmtCreate(timestr);

        user.setGmtModified(timestr);

        user.setPassword(ProjectUtils.md5(user.getPassword()));

        Integer nums = userService.addUser(user);

        if (nums > 0) {
            return ResultEntity.successWithoutData();
        } else {
            return ResultEntity.failed(ProjectConstant.USER_ADD_FAILED);
        }
    }

    @DeleteMapping(value = "/del/by/uids")
    @ApiOperation("根据用户id批量删除用户")
    @RequiresPermissions(value = {"user:delete"})
    public ResultEntity deleteByUids(@RequestBody List<Integer> uids) {

        Integer nums = userService.delUserByUids(uids);

        if (nums > 0) {
            return ResultEntity.successWithoutData();
        } else {
            return ResultEntity.failed(ProjectConstant.USER_CHANGE_FAILED);
        }
    }

    @DeleteMapping(value = "/del/by/{uid}")
    @ApiOperation("根据用户id删除单个用户")
    @RequiresPermissions(value = {"user:delete"})
    public ResultEntity deleteByUid(@PathVariable Integer uid) {

        Integer nums = userService.delUserByUId(uid);

        if (nums > 0) {
            return ResultEntity.successWithoutData();
        } else {
            return ResultEntity.failed(ProjectConstant.USER_DELETE_FAILED);
        }
    }


    /**
     * 分页获取用户列表
     *
     * @return
     */
    @GetMapping(value = "/get/usr/info/{page}/{offset}")
    @ApiOperation(value = "分页获取用户的信息")
    @RequiresPermissions(value = {"user:list"})
    public ResultEntity getUserList(@PathVariable Integer page,
                                    @PathVariable Integer offset) {

        PageInfo pageInfo = userService.getUserByPage(page, offset);

        Map<String, Object> rec = new HashMap<>();

        rec.put("total", pageInfo.getTotal());

        rec.put("data", pageInfo.getList());

        return ResultEntity.successWithData(rec);
    }


    @PostMapping(value = "/usr/login")
    @ApiOperation(value = "执行用户登录操作")
    @CancelLoginIntercept
    public ResultEntity userlogin(@RequestBody UserVO userVO) {

        // 将用户信息查询出来
        User user = userService.getUserByAccount(userVO.getAccount());

        // 当用户不存在时
        if (user == null) {
            return ResultEntity.failed(ProjectConstant.USER_FAILED_MESSAGE);
        }

        // 进行密码比对
        String pad = userVO.getPassword();

        String password = ProjectUtils.md5(pad);

        if (!Objects.equals(password, user.getPassword())) {
            // 密码比对失败
            return ResultEntity.failed(ProjectConstant.USER_FAILED_MESSAGE);
        }
        // 这里处理登录成功
        // 生成token
        String token = TokenUtils.produceToken();

        // 封装数据
        user.setPassword("");  // 清除密码

        Map<String, Object> redata = new HashMap<>();

        redata.put("user", user);

        redata.put("token", token);

        List<Map<String,Object>> auths = new ArrayList<>();

        Map<String,Object> temp = new HashMap<>();

        // 获取用户权限
        Set<String> permissions = userService.getPermissions(user.getUid());

        for (String permission : permissions) {

            temp.put(permission.replace(":",""),"");
        }
        redata.put("auth",temp);

        String red = JSON.toJSONString(redata);

        // 将token保存到redis中，设置失效时间为1h
        stringRedisTemplate.opsForValue().set(userVO.getAccount(), red, 1, TimeUnit.HOURS);

        // 将数据保存到shiro中，用于授权
        UsernamePasswordToken tok = new UsernamePasswordToken(String.valueOf(user.getUid()), "shiro");

        Subject subject = SecurityUtils.getSubject();

        subject.login(tok);

        // 将数据返回给用户
        return ResultEntity.successWithData(redata);
    }


    @PostMapping(value = "/usr/logout")
    @ApiOperation(value = "执行用户的退出操作")
    @CancelLoginIntercept
    public ResultEntity logout(@RequestBody Map<String, Object> res) {

        String account = (String) res.get("account");

        if(account==null){
            return ResultEntity.successWithoutData();
        }

        // redis中清除数据
        stringRedisTemplate.delete(account);

        return ResultEntity.successWithoutData();
    }


    @PutMapping(value = "/update/avator/by")
    @ApiOperation(value = "修改用户的头像")
    public ResultEntity updateUserAvator(@RequestBody UserAvatorVO user) {

        Integer nums = userService.updateUserAvatorByUid(user.getUid(), user.getHeadImg());

        return nums > 0 ? ResultEntity.successWithoutData() : ResultEntity.failed(ProjectConstant.AVATOR_CHANGE_FAILED);

    }

    @PostMapping(value = "/upload/avator/img")
    @ApiOperation(value = "用户头像上传")
    public Map<String, Object> uploadAvator(@RequestParam(value = "file") MultipartFile file) throws IOException, IOException {

        // 调用封装的oss上传文件的Utils
        ResultEntity result = OssUtils.uploadfile(ossConfig, "images/avatar"
                , file.getInputStream(), file.getOriginalFilename());


        Map<String, Object> map = new HashMap<>();
        Map<String, Object> map1 = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "上传成功！");
        map1.put("src", result.getData());
        map.put("data", map1);
        return map;
    }


}
